package com.src.xyzk_personal.EOL;

import java.util.Random;

import com.src.xyzk_personal.config.Common;
import com.src.xyzk_personal.config.Commonfunc;

import android.util.Log;

public class EolFunction {
	private static String TAG = "EolFunction";


	/**
	 * S盒
	 */
	static final int S_BOX[][] = { {0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76},
			{0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0},
			{0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15},
			{0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75},
			{0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84},
			{0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf},
			{0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8},
			{0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2},
			{0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73},
			{0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb},
			{0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79},
			{0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08},
			{0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a},
			{0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e},
			{0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf},
			{0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16} };

	/**
	 * 逆S盒
	 */
	static final int INVERSE_S_BOX[][] = { {0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb},
			{0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb},
			{0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e},
			{0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25},
			{0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92},
			{0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84},
			{0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06},
			{0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b},
			{0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73},
			{0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e},
			{0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b},
			{0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4},
			{0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f},
			{0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef},
			{0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61},
			{0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}};

	static int RC[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
	//巢湖生成PIN
	public static void cheryVinToPin(String vin, byte []pin){
		aes(vin,pin,"Chery_xinnengyuan_vintopin_12345");
	}

	public static void aes(String vin, byte []pin,String password){
		String passwordhex="43686572795F78696E6E656E677975616E5F76696E746F70696E5F3132333435";
		//		str2hex(password,passwordhex);
		int p[][]=new int[4][4];
		for (int m = 0; m < 4; ++m) {
			for (int i = 0; i < 4; ++i) {
				int indx = 4 * i + m;
				p[i][m] = 16 * c2i(passwordhex.charAt(indx)) + c2i(passwordhex.charAt(indx + 1));
			}
		}
		char []content = new char[33];
		for(int i=0;i<vin.length();i++){
			content[i]=vin.charAt(i);
		}

		//必须是16位，填充VIN前15位
		for (int j = 17; j < 32; ++j) {
			content[j] = vin.charAt(j - 17);
		}

		//存储结果
		char []encry = new char[33];
		//将文件转换成16字节的int型数组加密、解密
		for (int i = 0; i < 2; ++i) {

			int content_to_int[][]=new int[4][4];
			for (int j = 0; j < 4; ++j) {
				for (int k = 0; k < 4; ++k) {
					content_to_int[j][k] = content[j * 4 + k + 16 * i];
				}
			}
			aes_detail(content_to_int, p);
			for (int j = 0; j < 4; ++j) {
				for (int k = 0; k < 4; ++k) {
					encry[j * 4 + k + 16 * i] = (char) content_to_int[j][k];
				}
			}
		}
		pin[0]=(byte) encry[30];
		pin[1]=(byte) encry[31];
	}

	static void aes_detail(int content[][],  int password[][]){
		int p[][][]=new int[11][4][4];
		keyExpansion(password, p);
		int encode = 1;
		addRoundKey(content, p[0]);
		for (int i = 1; i <= 10; ++i) {
			subBytes(content, encode);
			shiftRows(content, encode);
			if (i != 10) {
				mixColumns(content, encode);
			}
			addRoundKey(content, p[i]);
		}
	}

	static void subBytes(int a[][], int encode){
		// encode 为1 代表字节替代，为0代表逆向字节替代
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				int temp = a[i][j] & 0xFF;
				int row = temp / 16;
				int column = temp % 16;
				if (encode==1)
					a[i][j] = S_BOX[row][column];
				else
					a[i][j] = INVERSE_S_BOX[row][column];
			}
		}
	}

	static void shiftRows(int a[][], int encode){
		//encode 为1代表行移位，为0代表逆向行移位
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < i; ++j) {
				if (encode==1) {
					int temp = a[i][0];
					a[i][0] = a[i][1];
					a[i][1] = a[i][2];
					a[i][2] = a[i][3];
					a[i][3] = temp;
				} else{
					int temp = a[i][3];
					a[i][3] = a[i][2];
					a[i][2] = a[i][1];
					a[i][1] = a[i][0];
					a[i][0] = temp;
				}
			}
		}
	}

	static void mixColumns(int a[][], int encode){
		//encode 为1代表列混淆，为0代表逆向列混淆
		for (int i = 0; i < 4; ++i) {
			int temp0 = a[0][i];
			int temp1 = a[1][i];
			int temp2 = a[2][i];
			int temp3 = a[3][i];
			if (encode!=0) {
				a[0][i] = aes_multiple(temp0, 2) ^ aes_multiple(temp1, 3) ^ temp2 ^ temp3;
				a[1][i] = temp0 ^ (aes_multiple(temp1, 2)) ^ (temp2 ^ aes_multiple(temp2, 2)) ^ temp3;
				a[2][i] = temp0 ^ temp1 ^ (aes_multiple(temp2, 2)) ^ (temp3 ^ aes_multiple(temp3, 2));
				a[3][i] = temp0 ^ (aes_multiple(temp0, 2)) ^ temp1 ^ temp2 ^ aes_multiple(temp3, 2);
			}else{
				a[0][i] = aes_multiple(temp0, 14) ^ aes_multiple(temp1, 11) ^ aes_multiple(temp2, 13) ^ aes_multiple(temp3, 9);
				a[1][i] = aes_multiple(temp0, 9) ^ aes_multiple(temp1, 14) ^ aes_multiple(temp2, 11) ^ aes_multiple(temp3, 13);
				a[2][i] = aes_multiple(temp0, 13) ^ aes_multiple(temp1, 9) ^ aes_multiple(temp2, 14) ^ aes_multiple(temp3, 11);
				a[3][i] = aes_multiple(temp0, 11) ^ aes_multiple(temp1, 13) ^ aes_multiple(temp2, 9) ^ aes_multiple(temp3, 14);
			}
		}
	}

	static void addRoundKey(int a[][], int k[][]){
		// 由于用w[11][4][4]表示W[44]导致行列转置，所以在进行异或操作的时候应该是a[i，j] 异或 k[j,i]
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				a[i][j] = a[i][j] ^ k[j][i];
			}
		}
	}

	//AES乘法计算
	static int aes_multiple(int a, int le){
		int thr = le & 0x8;
		int sec = le & 0x4;
		int fir = le & 0x2;
		int fir_mod = le % 2;
		int result = 0;
		if (thr!=0){
			int b = a;
			for (int i = 1; i <=3 ; ++i) {
				b = b<<1;
				if (b >= 256)
					b = b ^ 0x11b;
			}
			b = b % 256;
			result = result ^ b;
		}
		if (sec!=0){
			int b = a;
			for (int i = 1; i <=2 ; ++i) {
				b = b<<1;
				if (b >= 256)
					b = b ^ 0x11b;
			}
			b = b % 256;
			result = result ^ b;
		}
		if (fir!=0){
			int b = a << 1;
			if (b >= 256)
				b = b ^ 0x11b;
			b = b % 256;
			result = result ^ b;
		}
		if (fir_mod!=0)
			result = result ^ a;
		return  result;
	}

	static void keyExpansion(int key[][], int w[][][]){
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				w[0][i][j] = key[j][i];
			}
		}
		for (int i = 1; i < 11; ++i){
			for (int j = 0; j < 4; ++j) {
				int temp[]=new int[4];
				if (j == 0){
					temp[0] = w[i-1][3][1];
					temp[1] = w[i-1][3][2];
					temp[2] = w[i-1][3][3];
					temp[3] = w[i-1][3][0];
					for (int k = 0; k < 4; ++k) {
						int m = temp[k];
						int row = m / 16;
						int column = m % 16;
						temp[k] = S_BOX[row][column];
						if (k == 0){
							temp[k] = temp[k] ^ RC[i-1];
						}
					}
				} else{
					temp[0] = w[i][j-1][0];
					temp[1] = w[i][j-1][1];
					temp[2] = w[i][j-1][2];
					temp[3] = w[i][j-1][3];
				}
				for (int l = 0; l < 4; ++l) {

					w[i][j][l] = w[i-1][j][l] ^ temp[l];
				}

			}
		}
	}

	void str2hex(String src,String dec)
	{
		int len = src.length();
		for(int i = 0; i < len; i++)
		{
			//			char buf[3] = {0};
			//			sprintf_s(buf,3,"%02X", src[i]);
			//			memcpy(&dec[i*2],buf,2);
		}
	}

	//将字符转换为数值
	static int c2i(char ch) {
		// 如果是数字，则用数字的ASCII码减去48, 如果ch = '2' ,则 '2' - 48 = 2
		if(ch>='0'&&ch<='9')
			return ch - 48;

		// 如果是字母，但不是A~F,a~f则返回
		if( ch < 'A' || (ch > 'F' && ch < 'a') || ch > 'z' )
			return -1;

		// 如果是大写字母，则用数字的ASCII码减去55, 如果ch = 'A' ,则 'A' - 55 = 10
		// 如果是小写字母，则用数字的ASCII码减去87, 如果ch = 'a' ,则 'a' - 87 = 10
		if(ch>='A'&&ch<='Z'){
			return ch-55;
		}else if(ch>='a'&&ch<='z'){
			return ch-87;
		}
		return -1;
	}
	//产生PIN码
	public static void CreatePinCode(byte [] vin, byte [] Pin,int Psize)
	{
		//第一步，生成PIN
		Pin[0] = (byte) (vin[1] ^ vin[5] ^ vin[9]  ^ vin[13]);
		Pin[1] = (byte) (vin[2] ^ vin[6] ^ vin[10] ^ vin[14]);
		Pin[2] = (byte) (vin[3] ^ vin[7] ^ vin[11] ^ vin[15]);
		Pin[3] = (byte) (vin[4] ^ vin[8] ^ vin[12] ^ vin[16]);
	}
	//产生ESK
	public static void CreateESKCode(byte [] esk)
	{
		for(int i = 0 ; i < 16; i ++)
			esk[i] = (byte) (Math.random() * 0xFF);
	}
	//产生随机数
	public static byte [] CreateRandonAsc2Key(int mode,byte [] Pin,int len)
	{
		byte [] v_buf = null;
		Random rand = new Random();
		if(len < 0) return v_buf;
		v_buf = new byte[len];
		if(mode == 0) //由PIN码转换一组数据
		{
			for(int i = 0; i < 4; i ++)
			{
				v_buf[i * 4] = (byte) (0x30 + ((Pin[i]&0xFF) % 10));
				v_buf[i * 4 + 1] = (byte) (0x30 + (((Pin[i] >>> 2)&0xFF) % 10));
				v_buf[i * 4 + 2] = (byte) (0x30 + (((Pin[i] >>> 4)&0xFF) % 10));
				v_buf[i * 4 + 3] = (byte) (0x30 + (((Pin[i] >>> 6)&0xFF) % 10));
			}
		}
		else
		{
			v_buf[0] = (byte) (0x31 + rand.nextInt(8));
			for(int i = 1; i < len; i ++)
				v_buf[i] = (byte) (0x30 + rand.nextInt(9));
		}
		return v_buf;
	}
	//安全算法
	public static short seedToKey(byte[] pin,int level,byte[] seed,int Plen,byte[] key,int Psize)
	{
		short error = 0;
		int mask = 0;
		if(Common.Debug) Log.i(TAG,"Seed=" + Commonfunc.bytesToHexString(seed, 0, Plen));
		if (seed[1] == 0 && seed[2] == 0)
		{
			key[0] = 0x00;
			key[1] = 0x00;
			key[2] = 0x00;
			key[3] = 0x00;
		}
		else
		{
			if(level == 1) //27 01
				mask = 0x41578702;
			else	//27 03
				mask = ((pin[0]&0xFF) << 24) + ((pin[1]&0xFF) << 16) +((pin[2]&0xFF) << 8) + (pin[3]&0xFF);
			if(Common.Debug) Log.i(TAG,"mask=" + Integer.toHexString(mask));
			int  wort = ((seed[0]&0xFF) << 24) + ((seed[1]&0xFF) << 16) +((seed[2]&0xFF) << 8) + (seed[3]&0xFF);
			for (int i=0; i<40; i++)
			{
				if ((wort & 0x80000000) == 0x80000000)
				{
					wort = wort << 1;
					wort = wort ^ mask;
				}
				else
				{
					wort = wort << 1;
				}
			}
			for (int i=0; i<4; i++)
			{
				key[0] = (byte) ((wort >> 24) & 0xFF);
				key[1] = (byte) ((wort >> 16) & 0xFF);
				key[2] = (byte) ((wort >> 8) & 0xFF);
				key[3] = (byte) ((wort >> 0) & 0xFF);
			}
		}
		if(Common.Debug) Log.i(TAG,"Key=" + Commonfunc.bytesToHexString(key, 0,Psize));
		return error;
	}
	//力帆720PEPS安全算法
	public static void Peps720seedToKey(byte [] seed,byte [] key)
	{
		int i;
		int wort = 0;
		int mask = 0x4D5A16E3;
		/* The array for SEED starts with [1], the array for KEY starts with [0] */
		/* seed contains the SEED */
		/* length contains the number of bytes of seed */
		/* key contains the KEY  */
		/* retLen contains the number of bytes*/
		if (seed[1] == 0 && seed[2] == 0)
			return;
		else
		{
			wort = ((seed[0]&0xFF) << 24) + ((seed[1]&0xFF) << 16) +((seed[2]&0xFF) << 8) + (seed[3]&0xFF);
			for (i=0; i<40; i++)
			{
				if ((wort & 0x80000000) == 0x80000000)
				{
					wort = wort << 1;
					wort = wort ^ mask;
				}
				else
				{
					wort = wort << 1;
				}
			}
			for (i=0; i<4; i++)
			{
				key[i] = (byte) (wort >> (8*(3 - i)));
			}
		}
		return;
	}
	//GAOTIAN SRS安全算法
	public static boolean GaoTianSRSsafekey(byte[] seed,byte[] key)
	{
		byte [] Xor = {(byte) 0xE9,0x4A,0x22,(byte) 0x91};
		byte [] Cal = new byte[4];
		int Key = 0;
		for(int k = 0; k < 4; k ++)
			Cal[k] = (byte) (seed[k] ^ Xor[k]);
		Key = Key | (((Cal[3] & 0x0F) << 4) | (Cal[3] & 0xF0)) << 24;
		Key = Key | (((Cal[1] & 0x0F) << 4) | ((Cal[0] & 0xF0) >> 4)) << 16;
		Key = Key | ((Cal[1] & 0xF0) | ((Cal[2] & 0xF0) >> 4)) << 8;
		Key = Key | (((Cal[0] & 0x0F) << 4) | (Cal[2] & 0x0F));
		key[0] = (byte) ((Key >> 24) % 0xFF);
		key[1] = (byte) ((Key >> 16) & 0xFF);
		key[2] = (byte) ((Key >> 8) & 0xFF);
		key[3] = (byte) ((Key >> 0) & 0xFF);
		return true;
	}

	//GAOTIAN SRS安全算法
	public static boolean GaoTianABMsafekey(byte[] seed,byte[] key)
	{
		byte [] Xor = {(byte) 0x55,0x78,0x62,(byte) 0x18};
		//			byte [] Xor = {(byte) 0x68,0x86,0x24,(byte) 0x62};
		byte [] Cal = new byte[4];
		int Key = 0;
		for(int k = 0; k < 4; k ++)
			Cal[k] = (byte) (seed[k] ^ Xor[k]);
		//			Key = Key | (((Cal[3] & 0x0F) << 4) | (Cal[3] & 0xF0)) << 24;
		//			Key = Key | (((Cal[1] & 0x0F) << 4) | ((Cal[0] & 0xF0) >> 4)) << 16;
		//			Key = Key | ((Cal[1] & 0xF0) | ((Cal[2] & 0xF0) >> 4)) << 8;
		//			Key = Key | (((Cal[0] & 0x0F) << 4) | (Cal[2] & 0x0F));
		key[0] = (byte) (((Cal[3] & 0x0F) << 4) | (Cal[3] & 0xF0));
		key[1] = (byte) (((Cal[1] & 0x0F) << 4) | ((Cal[0] & 0xF0) >> 4));
		key[2] = (byte)((Cal[1] & 0xF0) | ((Cal[2] & 0xF0) >> 4));
		key[3] = (byte) (((Cal[0] & 0x0F) << 4) | (Cal[2] & 0x0F));
		return true;
	}
	//高田 X60算法
	public static boolean GaoTianX60SRSsafekey(byte[] seed,byte[] key)
	{
		int k1 = 0x248699;
		int k2 = 0x2927;
		int sed = (seed[0]&0xFF) * 0x10000 + (seed[1]&0xFF) * 0x100 + (seed[2]&0xFF);
		int A = (k2 * sed) + k1;
		int B = (k2 * sed) - k1;
		int Key = A ^ B;
		key[0] = (byte) ((Key >> 16) & 0xFF);
		key[1] = (byte) ((Key >> 8) & 0xFF);
		key[2] = (byte) ((Key >> 0) & 0xFF);
		return true;
	}
	//江淮联电安全算法
	public static void Jac_UAES_Encrypt(byte [] v, byte n, byte [] k, byte [] del)
	{
		byte z = v[n-1], y = v[0], delta = del[0], sum = 0, e=0,x;

		int p=0, q=0;
		if (n < 1)
		{
			return;
		}

		q = 6 + 52 / n;
		while (q-- > 0)
		{
			sum += delta;
			e = (byte) (sum >> 2 & 3);
			for (p = 0; p < n-1; p++)
			{
				y = v[p + 1];
				x = v[p];
				x += (byte) ((((z&0xFF) >> 5) ^ ((y&0xFF) << 2)) + (((y&0xFF) >> 3) ^
						((z&0xFF) << 4)) ^ (((sum&0xFF) ^ (y&0xFF)) + ((k[(p & 3) ^ e]&0xFF) ^ (z&0xFF))));
				v[p] = (byte) x;
				z = x;
			}
			y = v[0];
			x = v[n-1];
			x += (byte) ((((z&0xFF) >> 5) ^ ((y&0xFF) << 2)) + (((y&0xFF) >> 3) ^
					((z&0xFF) << 4)) ^ (((sum&0xFF) ^ (y&0xFF)) + ((k[(p & 3) ^ e]&0xFF) ^ (z&0xFF))));
			v[n-1] = (byte) x;
			z = x;
		}
	}
	//瑞风M5算法
	public static void jac_m5_encipher(int num_ruonds,byte [] seed,byte [] key,int [] constkey)
	{
		int i = 0;
		int v0 = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v1 = ((~seed[0])&0xFF) * 0x1000000 + ((~seed[1])&0xFF) * 0x10000 + ((~seed[2])&0xFF) * 0x100 + ((~seed[3])&0xFF);
		int sum = 0,delta = 0x9e3779B9;
		for(i = 0; i < num_ruonds; i ++)
		{
			v0 += (((v1 << 4) ^ (v1 >>> 5)) + v1) ^ (sum + constkey[sum & 3]);
			sum += delta;
			v1 += (((v0 << 4) ^ (v0 >>> 5)) + v0) ^ (sum + constkey[(sum >>> 11) & 3]);
		}
		key[0] = (byte) ((v0 >> 24) & 0xFF);
		key[1] = (byte) ((v0 >> 16) & 0xFF);
		key[2] = (byte) ((v0 >> 8) & 0xFF);
		key[3] = (byte) ((v0 >> 0) & 0xFF);
	}
	//联电ME788 S3 A30写VIN码算法
	public static void jac_s3_uaes_vin_safekey(byte [] seed,byte [] key)
	{
		int [] constkey = new int[4];
		constkey[0] = 0xC4945515;
		constkey[1] = 0x49534545;
		constkey[2] = 0x444B4559;
		constkey[3] = 0x14C474F4;
		jac_m5_encipher(2, seed, key, constkey);
	}
	//B11A TCU uaes安全算法
	public static void zotye_b11a_tcu_uaes_safekey(byte [] seed,byte [] key)
	{
		int [] constkey = new int[4];
		constkey[0] = 0x4C495551;
		constkey[1] = 0x49534545;
		constkey[2] = 0x444B4559;
		constkey[3] = 0x414C474F;
		jac_m5_encipher(2, seed, key, constkey);
	}
	public static void jac_M4_CTI_safekey(byte [] seed,byte [] key)
	{
		int [] constkey = new int[4];
		constkey[0] = 0x5E2A4981;
		constkey[1] = 0x5E2A4603;
		constkey[2] = 0x5E2A4147;
		constkey[3] = 0x5E2A4445;
		jac_m5_encipher(2, seed, key, constkey);
	}




	//JAC德尔福MT80/MT22.1安全算法
	public static void jac_delphi_80_22_1_safekey(byte [] seed,byte [] key)
	{
		byte [] jac_samask = {0x4A,0x57,0x41,0x43};
		byte [] cal = new byte[4];
		cal[0] = (byte) (seed[0] ^ jac_samask[0]);
		cal[1] = (byte) (seed[1] ^ jac_samask[1]);
		cal[2] = (byte) (seed[2] ^ jac_samask[2]);
		cal[3] = (byte) (seed[3] ^ jac_samask[3]);
		key[0] = (byte) ((cal[2]&0x0F) | (cal[2]&0xF0));
		key[1] = (byte) (((cal[0]&0x0F)<<4) | ((cal[1]&0xF0) >> 4));
		key[2] = (byte) ((cal[1]&0xF0) | ((cal[3]&0xF0) >> 4));
		key[3] = (byte) (((cal[0]&0x0F) << 4) | (cal[3]&0x0F));
	}
	//JAC德尔福MT20U2/MT22U/MT22.1.1  only 2byte
	public static void jac_delphi_20_22_22_1_1_safekey(byte [] seed,byte [] key)
	{
		byte [] samask = {'J','A'};
		byte [] cal = new byte[2];
		byte [] v_key = new byte[2];
		short key_value = 0;
		cal[0] = (byte) (seed[0] ^ samask[0]);
		cal[1] = (byte) (seed[1] ^ samask[1]);
		v_key[0] = (byte) ((cal[0]&0x0F) | (cal[1]&0xF0));
		v_key[1] = (byte) (((cal[0&0xF0]) >> 4) | ((cal[1]&0x0F) << 4));
		key_value = (short) ((v_key[0]&0xFF) * 0x100 + (v_key[1]&0xFF));
		key_value = (short) ~key_value;
		if(key_value == 0 || key_value == 0xFFFF)
		{
			key_value = 1;
		}
		//复制到KEY
		key[0] = (byte) ((key_value >> 8) & 0xFF);
		key[1] = (byte) (key_value & 0xFF);
	}
	//JDZ BAIC BCM safekey
	public static void hongyuan_bcm_safekey(byte[] seed,byte[] key)
	{
		int learnmask = 0x5827A3B6;
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		if(v_seed != 0)
		{
			for(int i = 0; i < 35; i ++)
			{
				if((v_seed & 0x80000000) == 0x80000000)
				{
					v_seed = v_seed << 1;
					v_seed = v_seed ^ learnmask;
				}
				else
				{
					v_seed = v_seed << 1;
				}
			}
			v_key = v_seed;
		}
		//输出到key
		key[0] = (byte) ((v_key >>> 24) & 0xFF);
		key[1] = (byte) ((v_key >>> 16) & 0xFF);
		key[2] = (byte) ((v_key >>> 8) & 0xFF);
		key[3] = (byte) ((v_key >>> 0) & 0xFF);
	}
	//JDZ BAIC EMS safekey
	public static void hongyuan_ems_safekey(byte[] seed,byte[] key)
	{
		int learnmask = 0x2459D1A3;
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		if(v_seed != 0)
		{
			for(int i = 0; i < 30; i ++)
			{
				if((v_seed & 0x80000000) == 0x80000000)
				{
					v_seed = v_seed << 1;
					v_seed = v_seed ^ learnmask;
				}
				else
				{
					v_seed = v_seed << 1;
				}
			}
			v_key = v_seed;
		}
		//输出到key
		key[0] = (byte) ((v_key >>> 24) & 0xFF);
		key[1] = (byte) ((v_key >>> 16) & 0xFF);
		key[2] = (byte) ((v_key >>> 8) & 0xFF);
		key[3] = (byte) ((v_key >>> 0) & 0xFF);
	}
	public static void hongyuan_eps_safekey(byte[] seed,byte[] key)
	{
		int learnmask = 0x62514039;
		//int learnmask = 0x5827A3B6;
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		if((v_seed&0xFFFF0000) != 0)
		{
			for(int i = 0; i < 35; ++ i)
			{
				if((v_seed & 0x80000000) == 0x80000000)
				{
					v_seed = v_seed << 1;
					v_seed = v_seed ^ learnmask;
				}
				else
				{
					v_seed = v_seed << 1;
				}
			}
			v_key = v_seed;
		}
		//输出到key
		key[0] = (byte) ((v_key >>> 24) & 0xFF);
		key[1] = (byte) ((v_key >>> 16) & 0xFF);
		key[2] = (byte) ((v_key >>> 8) & 0xFF);
		key[3] = (byte) ((v_key >>> 0) & 0xFF);
	}

	//JDZ BAIC ICM safekey
	public static void hongyuan_icm_safekey(byte[] seed,byte[] key)
	{
		int learnmask = 0x25340168;
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		if(v_seed != 0)
		{
			for(int i = 0; i < 30; i ++)
			{
				if((v_seed & 0x80000000) == 0x80000000)
				{
					v_seed = v_seed << 1;
					v_seed = v_seed ^ learnmask;
				}
				else
				{
					v_seed = v_seed << 1;
				}
			}
			v_key = v_seed;
		}
		//输出到key
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}
	public static void hongyuan_ABS_safekey(byte[] seed,byte[] key)
	{
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		v_key = (((v_seed >>> 4) ^ v_seed) << 3) ^ v_seed;
		//输出到key
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}

	public static void CHAOHU_ABS_safekey(byte[] seed,byte[] key)
	{
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);

		v_key = (((v_seed >> 2) ^ v_seed) << 3) ^ v_seed;
		//输出到key
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}

	public static void hongyuan_ACU_safekey(byte[] seed,byte[] key)
	{
		int constkey = 0x26031961;
		int v_seed = (seed[0]&0xFF) * 0x100 + (seed[1]&0xFF);
		v_seed = (v_seed >>> 5) | (v_seed << 23);
		v_seed *= 7;
		v_seed ^= constkey;
		//输出到key
		key[0] = (byte) ((v_seed >> 8) & 0xFF);
		key[1] = (byte) ((v_seed >> 0) & 0xFF);
	}
	public static void hongyuan_HUM_safekey(byte[] seed,byte[] key)
	{
		int [][] SS = { {
				0x2989, 0x0585, 0x16c6, 0x13c3, 0x1444, 0x1d0d, 0x2c8c, 0x2505,
				0x1d4d, 0x0343, 0x1808, 0x1e0e, 0x1141, 0x3ccc, 0x0aca, 0x2343,
				0x2808, 0x0444, 0x2000, 0x1d8d, 0x20c0, 0x22c2, 0x08c8, 0x1707,
				0x2585, 0x0f8f, 0x0303, 0x3b4b, 0x3b8b, 0x1303, 0x12c2, 0x2ece,
				0x3040, 0x0c8c, 0x3f0f, 0x2888, 0x3202, 0x1dcd, 0x36c6, 0x3444,
				0x2ccc, 0x1585, 0x0b0b, 0x1747, 0x1c4c, 0x1b4b, 0x3d8d, 0x0101,
				0x2404, 0x1c0c, 0x3343, 0x1888, 0x1000, 0x0ccc, 0x32c2, 0x19c9,
				0x2c0c, 0x27c7, 0x3242, 0x0383, 0x1b8b, 0x11c1, 0x0686, 0x09c9,
				0x2040, 0x1040, 0x2383, 0x2bcb, 0x0d0d, 0x3686, 0x1e8e, 0x0f4f,
				0x3787, 0x1a4a, 0x06c6, 0x3848, 0x2686, 0x1202, 0x2f8f, 0x15c5,
				0x2141, 0x03c3, 0x3484, 0x0141, 0x1242, 0x3d4d, 0x0d8d, 0x0808,
				0x1f0f, 0x1989, 0x0000, 0x1909, 0x0404, 0x1343, 0x37c7, 0x21c1,
				0x3dcd, 0x3646, 0x2f0f, 0x2707, 0x3080, 0x0b8b, 0x0e0e, 0x2b8b,
				0x2282, 0x2e4e, 0x1383, 0x0d4d, 0x2949, 0x3c4c, 0x0909, 0x0a0a,
				0x3f8f, 0x2fcf, 0x33c3, 0x05c5, 0x0787, 0x1404, 0x3ece, 0x2444,
				0x1ece, 0x2e0e, 0x0b4b, 0x1a0a, 0x0606, 0x2101, 0x2b4b, 0x2646,
				0x0202, 0x35c5, 0x1282, 0x0a8a, 0x0c0c, 0x3383, 0x3e4e, 0x10c0,
				0x3a4a, 0x0747, 0x1686, 0x25c5, 0x2606, 0x0080, 0x2d8d, 0x1fcf,
				0x2181, 0x3000, 0x3707, 0x2e8e, 0x3606, 0x1505, 0x2202, 0x3808,
				0x34c4, 0x2787, 0x0545, 0x0c4c, 0x0181, 0x29c9, 0x0484, 0x1787,
				0x3505, 0x0bcb, 0x0ece, 0x3c0c, 0x3141, 0x1101, 0x07c7, 0x0989,
				0x3545, 0x3bcb, 0x1aca, 0x38c8, 0x1484, 0x1949, 0x0282, 0x04c4,
				0x3fcf, 0x0949, 0x3909, 0x2747, 0x00c0, 0x0fcf, 0x17c7, 0x3888,
				0x0f0f, 0x0e8e, 0x0242, 0x2303, 0x1181, 0x2c4c, 0x1bcb, 0x2484,
				0x3404, 0x31c1, 0x0848, 0x02c2, 0x2f4f, 0x3d0d, 0x2d0d, 0x0040,
				0x3e8e, 0x3e0e, 0x3c8c, 0x01c1, 0x2a8a, 0x3a8a, 0x0e4e, 0x1545,
				0x3b0b, 0x1ccc, 0x2848, 0x3f4f, 0x1c8c, 0x18c8, 0x0a4a, 0x1646,
				0x3747, 0x2080, 0x2dcd, 0x0646, 0x3585, 0x2b0b, 0x2545, 0x3aca,
				0x23c3, 0x3989, 0x3181, 0x1f8f, 0x1e4e, 0x39c9, 0x26c6, 0x3282,
				0x3101, 0x2aca, 0x2d4d, 0x1f4f, 0x24c4, 0x30c0, 0x0dcd, 0x0888,
				0x1606, 0x3a0a, 0x1848, 0x14c4, 0x2242, 0x2909, 0x0707, 0x3303,
				0x28c8, 0x1b0b, 0x0505, 0x3949, 0x1080, 0x2a4a, 0x2a0a, 0x1a8a
		}, {
				0x3838, 0xe828, 0x2c2d, 0xa426, 0xcc0f, 0xdc1e, 0xb033, 0xb838,
				0xac2f, 0x6020, 0x5415, 0xc407, 0x4404, 0x6c2f, 0x682b, 0x581b,
				0xc003, 0x6022, 0x3033, 0xb435, 0x2829, 0xa020, 0xe022, 0xa427,
				0xd013, 0x9011, 0x1011, 0x0406, 0x1c1c, 0xbc3c, 0x3436, 0x480b,
				0xec2f, 0x8808, 0x6c2c, 0xa828, 0x1417, 0xc404, 0x1416, 0xf434,
				0xc002, 0x4405, 0xe021, 0xd416, 0x3c3f, 0x3c3d, 0x8c0e, 0x9818,
				0x2828, 0x4c0e, 0xf436, 0x3c3e, 0xa425, 0xf839, 0x0c0d, 0xdc1f,
				0xd818, 0x282b, 0x6426, 0x783a, 0x2427, 0x2c2f, 0xf031, 0x7032,
				0x4002, 0xd414, 0x4001, 0xc000, 0x7033, 0x6427, 0xac2c, 0x880b,
				0xf437, 0xac2d, 0x8000, 0x1c1f, 0xc80a, 0x2c2c, 0xa82a, 0x3434,
				0xd012, 0x080b, 0xec2e, 0xe829, 0x5c1d, 0x9414, 0x1818, 0xf838,
				0x5417, 0xac2e, 0x0808, 0xc405, 0x1013, 0xcc0d, 0x8406, 0xb839,
				0xfc3f, 0x7c3d, 0xc001, 0x3031, 0xf435, 0x880a, 0x682a, 0xb031,
				0xd011, 0x2020, 0xd417, 0x0002, 0x2022, 0x0404, 0x6828, 0x7031,
				0x0407, 0xd81b, 0x9c1d, 0x9819, 0x6021, 0xbc3e, 0xe426, 0x5819,
				0xdc1d, 0x5011, 0x9010, 0xdc1c, 0x981a, 0xa023, 0xa82b, 0xd010,
				0x8001, 0x0c0f, 0x4407, 0x181a, 0xe023, 0xec2c, 0x8c0d, 0xbc3f,
				0x9416, 0x783b, 0x5c1c, 0xa022, 0xa021, 0x6023, 0x2023, 0x4c0d,
				0xc808, 0x9c1e, 0x9c1c, 0x383a, 0x0c0c, 0x2c2e, 0xb83a, 0x6c2e,
				0x9c1f, 0x581a, 0xf032, 0x9012, 0xf033, 0x4809, 0x7838, 0xcc0c,
				0x1415, 0xf83b, 0x7030, 0x7435, 0x7c3f, 0x3435, 0x1010, 0x0003,
				0x6424, 0x6c2d, 0xc406, 0x7434, 0xd415, 0xb434, 0xe82a, 0x0809,
				0x7436, 0x1819, 0xfc3e, 0x4000, 0x1012, 0xe020, 0xbc3d, 0x0405,
				0xf83a, 0x0001, 0xf030, 0x282a, 0x5c1e, 0xa829, 0x5416, 0x4003,
				0x8405, 0x1414, 0x8809, 0x981b, 0xb030, 0xe425, 0x4808, 0x7839,
				0x9417, 0xfc3c, 0x1c1e, 0x8002, 0x2021, 0x8c0c, 0x181b, 0x5c1f,
				0x7437, 0x5414, 0xb032, 0x1c1d, 0x2425, 0x4c0f, 0x0000, 0x4406,
				0xec2d, 0x5818, 0x5012, 0xe82b, 0x7c3e, 0xd81a, 0xc809, 0xfc3d,
				0x3030, 0x9415, 0x6425, 0x3c3c, 0xb436, 0xe424, 0xb83b, 0x7c3c,
				0x0c0e, 0x5010, 0x3839, 0x2426, 0x3032, 0x8404, 0x6829, 0x9013,
				0x3437, 0xe427, 0x2424, 0xa424, 0xc80b, 0x5013, 0x080a, 0x8407,
				0xd819, 0x4c0c, 0x8003, 0x8c0f, 0xcc0e, 0x383b, 0x480a, 0xb437
		}, {
				0xa1a8, 0x8184, 0xd2d4, 0xd3d0, 0x5054, 0x111c, 0xa0ac, 0x2124,
				0x515c, 0x4340, 0x1018, 0x121c, 0x5150, 0xf0fc, 0xc2c8, 0x6360,
				0x2028, 0x4044, 0x2020, 0x919c, 0xe0e0, 0xe2e0, 0xc0c8, 0x1314,
				0xa1a4, 0x838c, 0x0300, 0x7378, 0xb3b8, 0x1310, 0xd2d0, 0xe2ec,
				0x7070, 0x808c, 0x333c, 0xa0a8, 0x3230, 0xd1dc, 0xf2f4, 0x7074,
				0xe0ec, 0x9194, 0x0308, 0x5354, 0x505c, 0x5358, 0xb1bc, 0x0100,
				0x2024, 0x101c, 0x7370, 0x9098, 0x1010, 0xc0cc, 0xf2f0, 0xd1d8,
				0x202c, 0xe3e4, 0x7270, 0x8380, 0x9398, 0xd1d0, 0x8284, 0xc1c8,
				0x6060, 0x5050, 0xa3a0, 0xe3e8, 0x010c, 0xb2b4, 0x929c, 0x434c,
				0xb3b4, 0x5258, 0xc2c4, 0x7078, 0xa2a4, 0x1210, 0xa3ac, 0xd1d4,
				0x6160, 0xc3c0, 0xb0b4, 0x4140, 0x5250, 0x717c, 0x818c, 0x0008,
				0x131c, 0x9198, 0x0000, 0x1118, 0x0004, 0x5350, 0xf3f4, 0xe1e0,
				0xf1fc, 0x7274, 0x232c, 0x2324, 0xb0b0, 0x8388, 0x020c, 0xa3a8,
				0xa2a0, 0x626c, 0x9390, 0x414c, 0x6168, 0x707c, 0x0108, 0x0208,
				0xb3bc, 0xe3ec, 0xf3f0, 0xc1c4, 0x8384, 0x1014, 0xf2fc, 0x6064,
				0xd2dc, 0x222c, 0x4348, 0x1218, 0x0204, 0x2120, 0x6368, 0x6264,
				0x0200, 0xf1f4, 0x9290, 0x8288, 0x000c, 0xb3b0, 0x727c, 0xd0d0,
				0x7278, 0x4344, 0x9294, 0xe1e4, 0x2224, 0x8080, 0xa1ac, 0xd3dc,
				0xa1a0, 0x3030, 0x3334, 0xa2ac, 0x3234, 0x1114, 0x2220, 0x3038,
				0xf0f4, 0xa3a4, 0x4144, 0x404c, 0x8180, 0xe1e8, 0x8084, 0x9394,
				0x3134, 0xc3c8, 0xc2cc, 0x303c, 0x7170, 0x1110, 0xc3c4, 0x8188,
				0x7174, 0xf3f8, 0xd2d8, 0xf0f8, 0x9094, 0x5158, 0x8280, 0xc0c4,
				0xf3fc, 0x4148, 0x3138, 0x6364, 0xc0c0, 0xc3cc, 0xd3d4, 0xb0b8,
				0x030c, 0x828c, 0x4240, 0x2320, 0x9190, 0x606c, 0xd3d8, 0xa0a4,
				0x3034, 0xf1f0, 0x4048, 0xc2c0, 0x636c, 0x313c, 0x212c, 0x4040,
				0xb2bc, 0x323c, 0xb0bc, 0xc1c0, 0xa2a8, 0xb2b8, 0x424c, 0x5154,
				0x3338, 0xd0dc, 0x6068, 0x737c, 0x909c, 0xd0d8, 0x4248, 0x5254,
				0x7374, 0xa0a0, 0xe1ec, 0x4244, 0xb1b4, 0x2328, 0x6164, 0xf2f8,
				0xe3e0, 0xb1b8, 0xb1b0, 0x939c, 0x525c, 0xf1f8, 0xe2e4, 0xb2b0,
				0x3130, 0xe2e8, 0x616c, 0x535c, 0xe0e4, 0xf0f0, 0xc1cc, 0x8088,
				0x1214, 0x3238, 0x5058, 0xd0d4, 0x6260, 0x2128, 0x0304, 0x3330,
				0xe0e8, 0x1318, 0x0104, 0x7178, 0x9090, 0x6268, 0x2228, 0x9298
		}, {
				0x0830, 0xc8e0, 0x0d21, 0x86a2, 0xcfc3, 0xced2, 0x83b3, 0x88b0,
				0x8fa3, 0x4060, 0x4551, 0xc7c3, 0x4440, 0x4f63, 0x4b63, 0x4b53,
				0xc3c3, 0x4262, 0x0333, 0x85b1, 0x0921, 0x80a0, 0xc2e2, 0x87a3,
				0xc3d3, 0x8191, 0x0111, 0x0602, 0x0c10, 0x8cb0, 0x0632, 0x4b43,
				0xcfe3, 0x8880, 0x4c60, 0x88a0, 0x0713, 0xc4c0, 0x0612, 0xc4f0,
				0xc2c2, 0x4541, 0xc1e1, 0xc6d2, 0x0f33, 0x0d31, 0x8e82, 0x8890,
				0x0820, 0x4e42, 0xc6f2, 0x0e32, 0x85a1, 0xc9f1, 0x0d01, 0xcfd3,
				0xc8d0, 0x0b23, 0x4662, 0x4a72, 0x0723, 0x0f23, 0xc1f1, 0x4272,
				0x4242, 0xc4d0, 0x4141, 0xc0c0, 0x4373, 0x4763, 0x8ca0, 0x8b83,
				0xc7f3, 0x8da1, 0x8080, 0x0f13, 0xcac2, 0x0c20, 0x8aa2, 0x0430,
				0xc2d2, 0x0b03, 0xcee2, 0xc9e1, 0x4d51, 0x8490, 0x0810, 0xc8f0,
				0x4753, 0x8ea2, 0x0800, 0xc5c1, 0x0313, 0xcdc1, 0x8682, 0x89b1,
				0xcff3, 0x4d71, 0xc1c1, 0x0131, 0xc5f1, 0x8a82, 0x4a62, 0x81b1,
				0xc1d1, 0x0020, 0xc7d3, 0x0202, 0x0222, 0x0400, 0x4860, 0x4171,
				0x0703, 0xcbd3, 0x8d91, 0x8991, 0x4161, 0x8eb2, 0xc6e2, 0x4951,
				0xcdd1, 0x4151, 0x8090, 0xccd0, 0x8a92, 0x83a3, 0x8ba3, 0xc0d0,
				0x8181, 0x0f03, 0x4743, 0x0a12, 0xc3e3, 0xcce0, 0x8d81, 0x8fb3,
				0x8692, 0x4b73, 0x4c50, 0x82a2, 0x81a1, 0x4363, 0x0323, 0x4d41,
				0xc8c0, 0x8e92, 0x8c90, 0x0a32, 0x0c00, 0x0e22, 0x8ab2, 0x4e62,
				0x8f93, 0x4a52, 0xc2f2, 0x8292, 0xc3f3, 0x4941, 0x4870, 0xccc0,
				0x0511, 0xcbf3, 0x4070, 0x4571, 0x4f73, 0x0531, 0x0010, 0x0303,
				0x4460, 0x4d61, 0xc6c2, 0x4470, 0xc5d1, 0x84b0, 0xcae2, 0x0901,
				0x4672, 0x0911, 0xcef2, 0x4040, 0x0212, 0xc0e0, 0x8db1, 0x0501,
				0xcaf2, 0x0101, 0xc0f0, 0x0a22, 0x4e52, 0x89a1, 0x4652, 0x4343,
				0x8581, 0x0410, 0x8981, 0x8b93, 0x80b0, 0xc5e1, 0x4840, 0x4971,
				0x8793, 0xccf0, 0x0e12, 0x8282, 0x0121, 0x8c80, 0x0b13, 0x4f53,
				0x4773, 0x4450, 0x82b2, 0x0d11, 0x0521, 0x4f43, 0x0000, 0x4642,
				0xcde1, 0x4850, 0x4252, 0xcbe3, 0x4e72, 0xcad2, 0xc9c1, 0xcdf1,
				0x0030, 0x8591, 0x4561, 0x0c30, 0x86b2, 0xc4e0, 0x8bb3, 0x4c70,
				0x0e02, 0x4050, 0x0931, 0x0622, 0x0232, 0x8480, 0x4961, 0x8393,
				0x0733, 0xc7e3, 0x0420, 0x84a0, 0xcbc3, 0x4353, 0x0a02, 0x8783,
				0xc9d1, 0x4c40, 0x8383, 0x8f83, 0xcec2, 0x0b33, 0x4a42, 0x87b3
		} };

		int v_seed = (seed[0]&0xFF) * 0x100 + (seed[1]&0xFF);
		int tempkeyX = v_seed % 4;
		int tempkeyY = (seed[0] ^ seed[1])&0xFF;
		//输出到key
		key[0] = (byte) ((SS[tempkeyX][tempkeyY] >> 8) & 0xFF);
		key[1] = (byte) ((SS[tempkeyX][tempkeyY] >> 0) & 0xFF);
	}
	public static void hongyuan_TCU_safekey(byte[] seed,byte[] key)
	{
		hongyuan_tcu_calc(seed,key);
		byte [] v_seed = new byte[2];
		byte [] v_key = new byte[2];
		v_seed[0] = seed[2];
		v_seed[1] = seed[3];
		hongyuan_tcu_calc(v_seed,v_key);
		//输出到key
		key[2] = v_key[0];
		key[3] = v_key[1];
	}
	private static void hongyuan_tcu_calc(byte[] seed,byte[] key)
	{
		byte seedH,seedL;
		seedH = seed[0];
		seedL = seed[1];
		seedH = (byte) (((seedH&0xFF) >>> 3) | ((seedH&0xFF) << 5));
		seedL = (byte) (((seedL&0xFF) >>> 3) | ((seedL&0xFF) << 5));

		seedH = (byte) (((seedH&0xAA) >>> 1) | ((seedH&0x55) << 1));
		seedL = (byte) (((seedL&0xAA) >>> 1) | ((seedL&0x55) << 1));

		seedH = (byte) (((seedH&0xFF) << 3)| ((seedL&0xFF) >>> 5));
		seedL = (byte) (((seedL&0xFF) << 3)| ((seedH&0xFF) >>> 5));

		byte Codf1 = (byte) 0xED;
		byte Codf2 = (byte) 0xCA;

		seedH ^= Codf1;
		seedL ^= Codf2;
		key[0] = seedH;
		key[1] = seedL;
	}
	public static void hongyuan_CreatePin(byte[] vin,byte[] pin)
	{
		pin[0] = (byte) (((hongyuan_GetVinCode(vin[0]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[16])) % 16) * 0x10 +
				((hongyuan_GetVinCode(vin[1]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[15])) % 16));
		pin[1] = (byte) (((hongyuan_GetVinCode(vin[2]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[14])) % 16) * 0x10 +
				((hongyuan_GetVinCode(vin[3]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[13])) % 16));
		pin[2] = (byte) (((hongyuan_GetVinCode(vin[4]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[12])) % 16) * 0x10 +
				((hongyuan_GetVinCode(vin[5]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[11])) % 16));
		//pin[3] = (byte) (((hongyuan_GetVinCode(vin[6]) + hongyuan_GetVinCode(vin[8])) % 16) * 0x10 +
		//		((hongyuan_GetVinCode(vin[7]) + hongyuan_GetVinCode(vin[8])) % 16));
	}
	public static void hongyuan_CreateESK(byte[] vin,byte[] esk)
	{
		byte [] bcSN = new byte[10];
		bcSN[0] = 'F';
		bcSN[1] = '1';
		bcSN[2] = 'A';
		int SN = (bcSN[0] + bcSN[1] + bcSN[2]) % 0x100;
		for(int j = 0; j < 16; j ++)
		{
			if(j < 9)
				esk[j] = (byte) ((hongyuan_GetVinCode(vin[j]) + SN + hongyuan_GetVinCode(vin[9])) % 0x100);
			else
				esk[j] = (byte) ((hongyuan_GetVinCode(vin[j+1]) + SN + hongyuan_GetVinCode(vin[9])) % 0x100);
		}
	}
	private static int hongyuan_GetVinCode(byte P)
	{
		int value = 0;
		if(P >= '0' && P <= '9')
			value = P - 0x30;
		else if(P >= 'A' && P <= 'H')
			value = P - 'A' + 10;
		else if(P >= 'J' && P <= 'N')
			value = P - 'J' + 18;
		else if(P =='P')
			value = 23;
		else if(P >= 'R' && P <= 'Z')
			value = P - 'R' + 24;
		else
			return 0;
		return value;
	}
	public static void hongyuan_SDM_safekey(byte[] seed,byte[] key)
	{
		int TOPBIT = 0x8000;
		int POLYNOM_1 = 0x4632;
		int POLYNOM_2 = 0x8752;
		int BITMASK = 0x0080;
		int INITIAL_REMINDER = 0xFFFE;
		int MSG_LEN = 2; /* seed length in bytes */
		byte [] bSeed = new byte[2];
		short remainder;
		byte n;
		byte i;
		bSeed[0] = seed[0]; /* MSB */
		bSeed[1] = seed[1]; /* LSB */
		remainder = (short) INITIAL_REMINDER;
		for (n = 0; n < MSG_LEN; n++)
		{
			/* Bring the next byte into the remainder. */
			remainder ^= ((bSeed[n]) << 8);

			/* Perform modulo-2 division, a bit at a time. */
			for (i = 0; i < 8; i++)
			{
				/* Try to divide the current data bit. */
				if ((remainder & TOPBIT) != 0)
				{
					if((remainder & BITMASK) != 0)
					{
						remainder = (short) ((remainder << 1) ^ POLYNOM_1);
					}
					else
					{
						remainder = (short) ((remainder << 1) ^ POLYNOM_2);
					}
				}
				else
				{
					remainder = (short) (remainder << 1);
				}
			}
		}
		key[0] = (byte) ((remainder >>> 8)&0xFF);
		key[1] = (byte) (remainder & 0xFF);
	}
	//合肥chery bcm
	public static void hefei_BCM_safekey(byte[] seed,byte[] key)
	{
		int TOPBIT = 0x8000;
		int POLYNOM_1 = 0x8408;
		int POLYNOM_2 = 0x8025;
		int BITMASK = 0x0080;
		int INITIAL_REMINDER = 0xFFFE;
		int MSG_LEN = 2; /* seed length in bytes */
		byte [] bSeed = new byte[2];
		short remainder;
		byte n;
		byte i;
		bSeed[0] = seed[0]; /* MSB */
		bSeed[1] = seed[1]; /* LSB */
		remainder = (short) INITIAL_REMINDER;
		for (n = 0; n < MSG_LEN; n++)
		{
			/* Bring the next byte into the remainder. */
			remainder ^= ((bSeed[n]) << 8);

			/* Perform modulo-2 division, a bit at a time. */
			for (i = 0; i < 8; i++)
			{
				/* Try to divide the current data bit. */
				if ((remainder & TOPBIT) != 0)
				{
					if((remainder & BITMASK) != 0)
					{
						remainder = (short) ((remainder << 1) ^ POLYNOM_1);
					}
					else
					{
						remainder = (short) ((remainder << 1) ^ POLYNOM_2);
					}
				}
				else
				{
					remainder = (short) (remainder << 1);
				}
			}
		}
		key[0] = (byte) ((remainder >>> 8)&0xFF);
		key[1] = (byte) (remainder & 0xFF);
	}

	public static void Chery_IMMO_safekey(byte[]seed, byte[]key,int pin){
		int k[] = {0xBE355A5C,0xD6952BBE,0x355A5CD6,0x952B784E };
		int[]seeds=new int[2];
		seeds[0] = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF) * 0x01;
		seeds[1] = (seed[4]&0xFF) * 0x1000000 + (seed[5]&0xFF) * 0x10000 + (seed[6]&0xFF) * 0x100 + (seed[7]&0xFF) * 0x01;
		long z=toUnsigned(seeds[1]), y=toUnsigned(seeds[0]),DELTA=0x9e3779b9,sum=0;
		int p , q ,e;
		if(pin!=0)k[0] ^= pin;
		q = 58;
		while (q-- > 0){
			sum =(sum+DELTA)&0x0FFFFFFFFL;
			e = (int) ((sum >> 2) & 3);
			for (p=0; p<1; p++){
				y = toUnsigned(seeds[1]);
				seeds[0] +=((z>>5^y<<2) + (y>>3^z<<4)^(sum^y) + (k[(p&3^e)]^z));
				z = toUnsigned(seeds[0]);
			}
			y = toUnsigned(seeds[0]);
			seeds[1]+=((z>>5^y<<2) + (y>>3^z<<4)^(sum^y) + (k[(p&3^e)]^z));
			z = toUnsigned(seeds[1]);
		}

		key[0] = (byte) ((seeds[0] >> 24) & 0xFF);
		key[1] = (byte) ((seeds[0] >> 16) & 0xFF);
		key[2] = (byte) ((seeds[0] >> 8) & 0xFF);
		key[3] = (byte) ((seeds[0] >> 0) & 0xFF);
		key[4] = (byte) ((seeds[1] >> 24) & 0xFF);
		key[5] = (byte) ((seeds[1] >> 16) & 0xFF);
		key[6] = (byte) ((seeds[1] >> 8) & 0xFF);
		key[7] = (byte) ((seeds[1] >> 0) & 0xFF);
	}

	static long toUnsigned(int sign){
		return sign&0x0FFFFFFFFL;
	}

	public static void Chery_CX62_EPB_SafeKey(byte[]seed,byte [] key)
	{
		byte[] v_mask= {0x15, 0x38, 0x55, 0x77};
		byte[] v_calData  =new byte[4];

		for (int i = 0; i < 4; i++){

			v_calData[i] = (byte) (seed[i] ^ v_mask[i]);
		}
		key[0] = (byte) (((v_calData[3]&0x0F)<<4) | (v_calData[3]&0xF0));
		key[1] = (byte) (((v_calData[1]&0x0F)<<4) | (v_calData[0]&0xF0)>>4);
		key[2] = (byte) ((v_calData[1]&0xF0)|((v_calData[2]&0xF0)>>4));
		key[3] = (byte) (((v_calData[0]&0x0F)<<4)|(v_calData[2]&0x0F));
	}
	//合肥MCU
	public static void hefei_MCU_safekey(byte[] seed,byte[] key)
	{
		int []mask={0x01,0x02,0x400,0x800,0x2000};
		int loop;
		byte passes;
		int bSeed =(seed[0]&0xFF) * 0x100 + (seed[1]&0xFF);
		passes=(byte)(((bSeed>>8)&0x07)+0x01);
		for(loop=1;loop<=passes;loop++){
			byte inc;
			byte count=0;
			for(inc=0;inc<5;inc++){
				if(0==(mask[inc]&bSeed)){

				}else{
					count++;
				}
			}
			bSeed=bSeed+(bSeed+(count&0x01));
		}
		key[0] = (byte) ((bSeed>> 8)&0xFF);
		key[1] = (byte) (bSeed & 0xFF);
	}
	//ZOTYE金坛项目算法汇总
	public static void Zotye_Greate_PinAndEsk(String vin,byte[] Pincode,byte[] EskCode)
	{
		DesVinToPin desvin = new DesVinToPin();
		desvin.GererateZotyePin(vin, Pincode);
		for(int i = 0; i < 4; i ++)
			System.arraycopy(Pincode, 0, EskCode, 4 * i, 4);
	}
	//B11 ICU
	public static void Zotye_icu_Encrypt(byte[] seed,int len,byte [] key)
	{
		byte [] xor = {0x14,0x11,0x75,(byte) 0xC2,0x62,(byte) 0xB3,(byte) 0xD2,0x56};
		byte [] cal = new byte[8];
		for(int i = 0; i < 4; i ++)
			cal[i] = (byte) (seed[i]^xor[i]);
		for(int i = 4; i < 8; i ++)
			cal[i] = (byte) (seed[i - 4] ^ xor[i]);
		for(int i = 0; i < 4; i ++)
			key[i] = (byte) (cal[i] + cal[i + 4]);
	}
	//B11 SRS
	public static void Zotye_srs_Encrypt(byte[] seed,int len,byte[] key)
	{
		int v_seed = seed[0] * 0x1000000 + seed[1] * 0x10000 + seed[2] * 0x100 + seed[3];
		int v_key = 0;
		int mult = 0x55555555;
		int sum = 0x24924925;
		v_key = mult * v_seed + sum;
		if(v_seed == 0) v_key = 0;
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}
	//纳恩防盗算法
	public static void Zotye_NaEnPEPSSafeKey(byte[] seed,byte[] key,int MASK)
	{
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		if (v_seed != 0)
		{
			for (int i=0; i < 35; i++ )
			{
				if((v_seed & 0x80000000) != 0)
				{
					v_seed = v_seed << 1;
					v_seed = v_seed ^ MASK;
				}
				else
				{
					v_seed = v_seed << 1;
				}
			}
			v_key = v_seed & 0xFFFFFFFF;
		}
		key[0] = (byte) ((v_key >>> 24) & 0xFF);
		key[1] = (byte) ((v_key >>> 16) & 0xFF);
		key[2] = (byte) ((v_key >>> 8) & 0xFF);
		key[3] = (byte) ((v_key >>> 0) & 0xFF);
	}
	//B11 TCU算法
	public static void Zotye_TCU_Safekey(byte[] seed,byte[] key)
	{
		long v0 = (seed[0] & 0xFF) * 0x1000000 + (seed[1] & 0xFF) * 0x10000 + (seed[2] & 0xFF) * 0x100 + (seed[3] & 0xFF);
		long v1 = (~seed[0] & 0xFF) * 0x1000000 + (~seed[1] & 0xFF) * 0x10000 + (~seed[2] & 0xFF) * 0x100 + (~seed[3] & 0xFF);
		long sum = 0;
		long delta = 0x9E3779B9;
		long [] k = {0,0,0,0};
		k[0] =  0x4C495551;
		k[1] =  0x49534545;
		k[2] =  0x444B4559;
		k[3] =  0x414C474F;
		for(int i = 0; i < 2; i ++)
		{
			v0 +=  (((v1 << 4) ^ ((v1 >> 5)& 0x07FFFFFF)) + v1) ^ (sum + k[(int) (sum & 3)]);
			sum += delta;
			v1 +=  (((v0 << 4) ^ ((v0 >> 5)& 0x07FFFFFF)) + v0) ^ (sum + k[(int) ((sum>>11) & 3)]);
		}
		key[0] = (byte) ((v0 >>> 24) & 0xFF);
		key[1] = (byte) ((v0 >>> 16) & 0xFF);
		key[2] = (byte) ((v0 >>> 8) & 0xFF);
		key[3] = (byte) ((v0 >>> 0) & 0xFF);
	}

	//B11 TPMS算法
	public static void Zotye_tpms_calckey(byte[] seed,byte[] key)
	{
		key[0] = (byte) ((~seed[0])<<1);
		key[1] = (byte) ((~seed[1])<<1);
	}
	public static void Zotye_bcm_calcKey(byte[] seed,byte[] key)
	{
		int TOPBIT = 0x8000;
		int POLYNOM_1 = 0x8408;
		int POLYNOM_2 = 0x8025;
		int BITMASK	= 0x0080;
		int INITIAL_REMINDER = 0xFFFE;
		int MSG_LEN = 2; /* seed length in bytes */
		byte [] bSeed = new byte[2];
		int remainder;
		byte n;
		byte i;
		bSeed[0] = seed[0]; /* MSB */
		bSeed[1] = seed[1]; /* LSB */
		remainder = INITIAL_REMINDER;
		for (n = 0; n < MSG_LEN; n++)
		{
			/* Bring the next byte into the remainder. */
			remainder ^= ((bSeed[n]) << 8);
			/* Perform modulo-2 division, a bit at a time. */
			for (i = 0; i < 8; i++)
			{
				/* Try to divide the current data bit. */
				if ((remainder & TOPBIT) > 0)
				{
					if((remainder & BITMASK) > 0)
					{
						remainder = (remainder << 1) ^ POLYNOM_1;
					}
					else
					{
						remainder = (remainder << 1) ^ POLYNOM_2;
					}
				}
				else
				{
					remainder = (remainder << 1);
				}
			}
		}
		/* The final remainder is the key */
		key[0] = (byte) ((remainder >> 8) & 0xFF);
		key[1] = (byte) (remainder & 0xFF);
	}
	public static void Zotye_T22_icm_Safekey(byte[] seed,byte[] key)
	{
		byte[] Xor = {0x14,0x11,0x75,(byte) 0xC2,0x62,(byte) 0xB3,(byte) 0xD2,0x56};
		byte[] cal = new byte[8];
		for(int i= 0;i < 4;i++)
		{
			cal[i] = (byte) (seed[i] ^ Xor[i]);
		}
		for(int i= 4;i < 8;i++)
		{
			cal[i] = (byte) (seed[i-4] ^ Xor[i]);
		}
		for(int i= 0;i < 4;i++)
		{
			key[i] = (byte) (cal[i] + cal[i + 4]);
		}
	}
	public static void Zotye_B11A_icm_Safekey(byte[] seed,byte[] key)
	{
		byte[] Xor = {0x14,0x11,0x75,(byte) 0xC2,0x62,(byte) 0xB3,(byte) 0xD2,0x56};
		byte[] cal = new byte[8];
		for(int i= 0;i < 4;i++)
		{
			cal[i] = (byte) (seed[i] ^ Xor[i]);
		}
		for(int i= 4;i < 8;i++)
		{
			cal[i] = (byte) (seed[i-4] ^ Xor[i]);
		}
		for(int i= 0;i < 4;i++)
		{
			key[i] = (byte) (cal[i] + cal[i + 4]);
		}
	}
	//UAES ME1788
	public static void Zotye_T22_uaes_safekey(byte [] seed,byte [] key)
	{
		int [] constkey = new int[4];
		constkey[0] = 0x4C495551;
		constkey[1] = 0x49534545;
		constkey[2] = 0x444B4559;
		constkey[3] = 0x414C474F;
		jac_m5_encipher(2, seed, key, constkey);
	}
	//delphi
	public static void Zotye_B11A_Delphi_Safekey(byte [] seed, byte [] key)
	{
		byte [] cal = new byte[4];
		cal[0] = (byte) (seed[0] ^ 0xAF);
		cal[1] = (byte) (seed[1] ^ 0x9E);
		cal[2] = (byte) (seed[2] ^ 0x01);
		cal[3] = (byte) (seed[3] ^ 0x66);
		key[0] = (byte) ((cal[2]&0x0F) | (cal[2]&0xF0));
		key[1] = (byte) (((cal[0]&0x0F) <<4) | ((cal[1]&0xF0)>> 4));
		key[2] = (byte) ((cal[1]&0xF0) | ((cal[3]&0xF0) >> 4));
		key[3] = (byte) (((cal[0]&0x0F) << 4) | (cal[3]&0x0F));
	}
	public static void Zotye_T22_TCU_GenerateKey(byte[] seed, byte[] key)
	{
		int   project_code;
		int   temp_value;
		int   seed_r;
		int   key_r;
		int PROJECT_ZORRO = 0x5A4F;  //A02
		int PROJECT_ZEBRA = 0x5A45;	//T22
		int SEED_MULT = 0x449C;
		seed_r = (seed[0]&0xFF) * 0x100 + (seed[1]&0xFF);

		/* Calculate the key out of the stored SEED
		 * Step 1: Multiply the SEED with a security-code
		 * Step 2: XOR the key with a project identifier.
		 *       The project identifier is retrieved out of Release information,
		 *       and scrambled
		 * */
		project_code = 0;
		temp_value = 0;

		temp_value = PROJECT_ZEBRA;
		project_code =   (temp_value << 1) & 0xFE;
		project_code |= ((temp_value >> 7) & 0x1);

		project_code |= ((temp_value >> 1) & 0x7F00);
		project_code |= ((temp_value << 7) & 0x8000);

		key_r = (seed_r  * SEED_MULT) ^ project_code;
		key[0] = (byte)((key_r >> 8)&0xFF);
		key[1] = (byte)(key_r & 0xFF);
	}
	public static void Zotye_T22_SRS_Safekey(byte[] seed,byte[] key)
	{
		int MULT_CONST = 0x55555555;
		int SUM_CONST = 0x24924925;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v_key = MULT_CONST * v_seed + SUM_CONST;
		if(v_seed == 0) v_key = 0;
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}
	//TBOX
	public static void Zotye_T22_ABS_Safekey(byte[] seed,byte[] key)
	{
		int unlockkey = 0;
		int unlockseed = 0;
		int undefineseed = 0xFFFFFFFF;
		int seedmask = 0x80000000;
		int shiftbit = 1;
		//int algorithmask = 0x42313131; //B11
		int algorithmask = 0x54323231; //T22
		byte u1;
		int u2;
		long u4;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v_key = 0;
		int i = 0;

		v_key = unlockkey;
		if(!((v_seed == undefineseed) || (v_seed == unlockseed)))
		{
			for(i = 0; i < 35; i ++)
			{
				if((v_seed & seedmask) != 0)
				{
					v_seed = v_seed << shiftbit;
					v_seed = v_seed ^ algorithmask;
				}
				else
				{
					v_seed = v_seed << shiftbit;
				}
			}
			v_key = v_seed;
		}
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}
	public static void Zotye_B11_Zotye_Safekey(byte[] seed,byte[] key)
	{
		int unlockkey = 0;
		int unlockseed = 0;
		int undefineseed = 0xFFFFFFFF;
		int seedmask = 0x80000000;
		int shiftbit = 1;
		int algorithmask = 0x42313131; //B11
		//int algorithmask = 0x54323231; //T22
		byte u1;
		int u2;
		long u4;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v_key = 0;
		int i = 0;

		v_key = unlockkey;
		if(!((v_seed == undefineseed) || (v_seed == unlockseed)))
		{
			for(i = 0; i < 35; i ++)
			{
				if((v_seed & seedmask) != 0)
				{
					v_seed = v_seed << shiftbit;
					v_seed = v_seed ^ algorithmask;
				}
				else
				{
					v_seed = v_seed << shiftbit;
				}
			}
			v_key = v_seed;
		}
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}

	public static void Zotye_B01_Stand_Safekey(byte[] seed,byte[] key)
	{
		int unlockkey = 0;
		int unlockseed = 0;
		int undefineseed = 0xFFFFFFFF;
		int seedmask = 0x80000000;
		int shiftbit = 1;
		int algorithmask = 0x42303131;
		byte u1;
		int u2;
		long u4;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v_key = 0;
		int i = 0;

		v_key = unlockkey;
		if(!((v_seed == undefineseed) || (v_seed == unlockseed)))
		{
			for(i = 0; i < 35; i ++)
			{
				if((v_seed & seedmask) != 0)
				{
					v_seed = v_seed << shiftbit;
					v_seed = v_seed ^ algorithmask;
				}
				else
				{
					v_seed = v_seed << shiftbit;
				}
			}
			v_key = v_seed;
		}
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}
	public static void Zotye_E01_ABS_Safekey(byte[] seed,byte[] key)
	{
		int unlockkey = 0;
		int unlockseed = 0;
		int undefineseed = 0xFFFFFFFF;
		int seedmask = 0x80000000;
		int shiftbit = 1;
		int algorithmask = 0x45303131;
		byte u1;
		int u2;
		long u4;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v_key = 0;
		int i = 0;

		v_key = unlockkey;
		if(!((v_seed == undefineseed) || (v_seed == unlockseed)))
		{
			for(i = 0; i < 35; i ++)
			{
				if((v_seed & seedmask) != 0)
				{
					v_seed = v_seed << shiftbit;
					v_seed = v_seed ^ algorithmask;
				}
				else
				{
					v_seed = v_seed << shiftbit;
				}
			}
			v_key = v_seed;
		}
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}


	public static void M1AEV_2018_IMMO_safekey(byte[] seed,byte[] key)
	{
		int TOPBIT = 0x8000;
		int POLYNOM_1 = 0x8408;
		int POLYNOM_2 = 0x8025;
		int BITMASK = 0x0080;
		int INITIAL_REMINDER = 0xFFFE;
		int MSG_LEN = 2; /* seed length in bytes */
		byte [] bSeed = new byte[2];
		short remainder;
		byte n;
		byte i;
		bSeed[0] = seed[0]; /* MSB */
		bSeed[1] = seed[1]; /* LSB */
		remainder = (short) INITIAL_REMINDER;
		for (n = 0; n < MSG_LEN; n++)
		{
			/* Bring the next byte into the remainder. */
			remainder ^= ((bSeed[n]) << 8);

			/* Perform modulo-2 division, a bit at a time. */
			for (i = 0; i < 8; i++)
			{
				/* Try to divide the current data bit. */
				if ((remainder & TOPBIT) != 0)
				{
					if((remainder & BITMASK) != 0)
					{
						remainder = (short) ((remainder << 1) ^ POLYNOM_1);
					}
					else
					{
						remainder = (short) ((remainder << 1) ^ POLYNOM_2);
					}
				}
				else
				{
					remainder = (short) (remainder << 1);
				}
			}
		}
		key[0] = (byte) ((remainder >>> 8)&0xFF);
		key[1] = (byte) (remainder & 0xFF);
	}
	public static boolean Chery_JX65_Safekey(byte[] seed,byte[] key,String Psys)
	{
		if(Psys.equals("PEPS1") || Psys.equals("EMS1"))
		{
			EolFunction.Chery_IMMO_safekey(seed, key,0);
		}
		else if(Psys.equals("ESP1") || Psys.equals("DCT1"))
		{
			S32EV_ABS_safekey(seed, key);
		}
		else if(Psys.equals("EPB1"))
		{
			Chery_CX62_EPB_SafeKey(seed, key);
		}
		else if(Psys.equals("FCM1"))
			EolFunction.Cx62B_FCM_Level1(seed, key,0x29D6);
		else if(Psys.equals("FRM1"))
			EolFunction.Cx62B_FCM_Level2(seed, key,0x5600);
		else
			hefei_BCM_safekey(seed, key);
		return true;
	}
	static long  ReverseBitsInWord00(long Num)
	{
		long ret = 0;
		int i;
		for(i=0;i<32;i++)
		{
			//ret <<= 1;
			ret = (ret&0xFFFFFFFF) << 1;
			ret|=Num&0x01;
			// Num >>>= 1;
			Num = (Num&0xFFFFFFFF) >>> 1;
		}
		return ret;
	}
	public static long Changan_SafeCode_level(byte[] seed,byte[] key,int Pkey)
	{
		byte [] key1 = new byte[4];
		byte [] key2 = new byte[4];
		byte [] seed2 = new byte[4];
		byte [] AppKeyConst = new byte[4];

		long seed_Rcv,Rota_seed,key1_32b,key2_32b,sum;
		AppKeyConst[0] = (byte) ((Pkey >>> 24) & 0xFF);
		AppKeyConst[1] = (byte) ((Pkey >>> 16) & 0xFF);
		AppKeyConst[2] = (byte) ((Pkey >>> 8) & 0xFF);
		AppKeyConst[3] = (byte) ((Pkey >>> 0) & 0xFF);
		seed_Rcv= (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);


		key1[0]=(byte) (seed[0]^AppKeyConst[0]);
		key1[1]=(byte) (seed[1]^AppKeyConst[1]);
		key1[2]=(byte) (seed[2]^AppKeyConst[2]);
		key1[3]=(byte) (seed[3]^AppKeyConst[3]);

		Rota_seed=ReverseBitsInWord00(seed_Rcv);

		seed2[3]= (byte) (Rota_seed&0xFF);
		seed2[2]=(byte) ((Rota_seed>>>8)&0xff);
		seed2[1]=(byte) ((Rota_seed>>>16)&0xff);
		seed2[0]=(byte) ((Rota_seed>>>24)&0xff);

		key2[0]= (byte) (seed2[0]^AppKeyConst[0]);
		key2[1]= (byte) (seed2[1]^AppKeyConst[1]);
		key2[2]= (byte) (seed2[2]^AppKeyConst[2]);
		key2[3]= (byte) (seed2[3]^AppKeyConst[3]);

		key1_32b= (key1[0]&0xFF) * 0x1000000 + (key1[1]&0xFF) * 0x10000 + (key1[2]&0xFF) * 0x100 + (key1[3]&0xFF);

		key2_32b= (key2[0]&0xFF) * 0x1000000 + (key2[1]&0xFF) * 0x10000 + (key2[2]&0xFF) * 0x100 + (key2[3]&0xFF);

		sum=(key1_32b&0xFFFFFFFF)+ (key2_32b&0xFFFFFFFF);

		key[0]=(byte) ((sum>>>24)&0xff);
		key[1]=(byte) ((sum>>>16)&0xff);
		key[2]=(byte) ((sum>>>8)&0xff);
		key[3]=(byte) (sum&0xff);

		return sum;
	}
	public static void S32EV_ABS_safekey(byte[] seed,byte[] key)
	{
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		v_key=((((v_seed>>2)^v_seed)<<3)^v_seed);
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}

	public static void M1AEV_2018_TCU_safekey(byte[] seed,byte[] key)
	{
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		v_key=((((v_seed>>2)^v_seed)<<3)^v_seed);
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}

	public static void CalcCRC(byte[] data,int datasize,byte[] checksum){

		int resul_crc=0;
		int crc =0xffff;
		int temp=0;
		int i=0;
		int[] crctab ={ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
				0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
				0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
				0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
				0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
				0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
				0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
				0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
				0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
				0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
				0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
				0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
				0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
				0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
				0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
				0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
				0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
				0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
				0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
				0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
				0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
				0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
				0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
				0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
				0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
				0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
				0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
				0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
				0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
				0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
				0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
				0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
		for ( i = 0; i < datasize; i++)
		{
			temp=((crc>>8)^data[i])&0xff;

			crc=((crc<<8)^crctab[temp])&0xFFFF;
		}
		resul_crc=crc;
		checksum[0]=(byte) ((byte) (resul_crc>>8)&0xff);
		checksum[1]=(byte) ((byte) (resul_crc&0xff));
	}

	public static byte[] Crc32(byte []pData,int size ){
		int[] crc32Tab = { 0x00000000 , 0x77073096 ,
				0xEE0E612C ,  0x990951BA ,  0x076DC419 ,  0x706AF48F ,  0xE963A535 ,
				0x9E6495A3 ,  0x0EDB8832 ,  0x79DCB8A4 ,  0xE0D5E91E ,  0x97D2D988 ,
				0x09B64C2B ,  0x7EB17CBD ,  0xE7B82D07 ,  0x90BF1D91 ,  0x1DB71064 ,
				0x6AB020F2 ,  0xF3B97148 ,  0x84BE41DE ,  0x1ADAD47D ,  0x6DDDE4EB ,
				0xF4D4B551 ,  0x83D385C7 ,  0x136C9856 ,  0x646BA8C0 ,  0xFD62F97A ,
				0x8A65C9EC ,  0x14015C4F ,  0x63066CD9 ,  0xFA0F3D63 ,  0x8D080DF5 ,
				0x3B6E20C8 ,  0x4C69105E ,  0xD56041E4 ,  0xA2677172 ,  0x3C03E4D1 ,
				0x4B04D447 ,  0xD20D85FD ,  0xA50AB56B ,  0x35B5A8FA ,  0x42B2986C ,
				0xDBBBC9D6 ,  0xACBCF940 ,  0x32D86CE3 ,  0x45DF5C75 ,  0xDCD60DCF ,
				0xABD13D59 ,  0x26D930AC ,  0x51DE003A ,  0xC8D75180 ,  0xBFD06116 ,
				0x21B4F4B5 ,  0x56B3C423 ,  0xCFBA9599 ,  0xB8BDA50F ,  0x2802B89E ,
				0x5F058808 ,  0xC60CD9B2 ,  0xB10BE924 ,  0x2F6F7C87 ,  0x58684C11 ,
				0xC1611DAB ,  0xB6662D3D ,  0x76DC4190 ,  0x01DB7106 ,  0x98D220BC ,
				0xEFD5102A ,  0x71B18589 ,  0x06B6B51F ,  0x9FBFE4A5 ,  0xE8B8D433 ,
				0x7807C9A2 ,  0x0F00F934 ,  0x9609A88E ,  0xE10E9818 ,  0x7F6A0DBB ,
				0x086D3D2D ,  0x91646C97 ,  0xE6635C01 ,  0x6B6B51F4 ,  0x1C6C6162 ,
				0x856530D8 ,  0xF262004E ,  0x6C0695ED ,  0x1B01A57B ,  0x8208F4C1 ,
				0xF50FC457 ,  0x65B0D9C6 ,  0x12B7E950 ,  0x8BBEB8EA ,  0xFCB9887C ,
				0x62DD1DDF ,  0x15DA2D49 ,  0x8CD37CF3 ,  0xFBD44C65 ,  0x4DB26158 ,
				0x3AB551CE ,  0xA3BC0074 ,  0xD4BB30E2 ,  0x4ADFA541 ,  0x3DD895D7 ,
				0xA4D1C46D ,  0xD3D6F4FB ,  0x4369E96A ,  0x346ED9FC ,  0xAD678846 ,
				0xDA60B8D0 ,  0x44042D73 ,  0x33031DE5 ,  0xAA0A4C5F ,  0xDD0D7CC9 ,
				0x5005713C ,  0x270241AA ,  0xBE0B1010 ,  0xC90C2086 ,  0x5768B525 ,
				0x206F85B3 ,  0xB966D409 ,  0xCE61E49F ,  0x5EDEF90E ,  0x29D9C998 ,
				0xB0D09822 ,  0xC7D7A8B4 ,  0x59B33D17 ,  0x2EB40D81 ,  0xB7BD5C3B ,
				0xC0BA6CAD ,  0xEDB88320 ,  0x9ABFB3B6 ,  0x03B6E20C ,  0x74B1D29A ,
				0xEAD54739 ,  0x9DD277AF ,  0x04DB2615 ,  0x73DC1683 ,  0xE3630B12 ,
				0x94643B84 ,  0x0D6D6A3E ,  0x7A6A5AA8 ,  0xE40ECF0B ,  0x9309FF9D ,
				0x0A00AE27 ,  0x7D079EB1 ,  0xF00F9344 ,  0x8708A3D2 ,  0x1E01F268 ,
				0x6906C2FE ,  0xF762575D ,  0x806567CB ,  0x196C3671 ,  0x6E6B06E7 ,
				0xFED41B76 ,  0x89D32BE0 ,  0x10DA7A5A ,  0x67DD4ACC ,  0xF9B9DF6F ,
				0x8EBEEFF9 ,  0x17B7BE43 ,  0x60B08ED5 ,  0xD6D6A3E8 ,  0xA1D1937E ,
				0x38D8C2C4 ,  0x4FDFF252 ,  0xD1BB67F1 ,  0xA6BC5767 ,  0x3FB506DD ,
				0x48B2364B ,  0xD80D2BDA ,  0xAF0A1B4C ,  0x36034AF6 ,  0x41047A60 ,
				0xDF60EFC3 ,  0xA867DF55 ,  0x316E8EEF ,  0x4669BE79 ,  0xCB61B38C ,
				0xBC66831A ,  0x256FD2A0 ,  0x5268E236 ,  0xCC0C7795 ,  0xBB0B4703 ,
				0x220216B9 ,  0x5505262F ,  0xC5BA3BBE ,  0xB2BD0B28 ,  0x2BB45A92 ,
				0x5CB36A04 ,  0xC2D7FFA7 ,  0xB5D0CF31 ,  0x2CD99E8B ,  0x5BDEAE1D ,
				0x9B64C2B0 ,  0xEC63F226 ,  0x756AA39C ,  0x026D930A ,  0x9C0906A9 ,
				0xEB0E363F ,  0x72076785 ,  0x05005713 ,  0x95BF4A82 ,  0xE2B87A14 ,
				0x7BB12BAE ,  0x0CB61B38 ,  0x92D28E9B ,  0xE5D5BE0D ,  0x7CDCEFB7 ,
				0x0BDBDF21 ,  0x86D3D2D4 ,  0xF1D4E242 ,  0x68DDB3F8 ,  0x1FDA836E ,
				0x81BE16CD ,  0xF6B9265B ,  0x6FB077E1 ,  0x18B74777 ,  0x88085AE6 ,
				0xFF0F6A70 ,  0x66063BCA ,  0x11010B5C ,  0x8F659EFF ,  0xF862AE69 ,
				0x616BFFD3 ,  0x166CCF45 ,  0xA00AE278 ,  0xD70DD2EE ,  0x4E048354 ,
				0x3903B3C2 ,  0xA7672661 ,  0xD06016F7 ,  0x4969474D ,  0x3E6E77DB ,
				0xAED16A4A ,  0xD9D65ADC ,  0x40DF0B66 ,  0x37D83BF0 ,  0xA9BCAE53 ,
				0xDEBB9EC5 ,  0x47B2CF7F ,  0x30B5FFE9 ,  0xBDBDF21C ,  0xCABAC28A ,
				0x53B39330 ,  0x24B4A3A6 ,  0xBAD03605 ,  0xCDD70693 ,  0x54DE5729 ,
				0x23D967BF ,  0xB3667A2E ,  0xC4614AB8 ,  0x5D681B02 ,  0x2A6F2B94 ,
				0xB40BBE37 ,  0xC30C8EA1 ,  0x5A05DF1B ,  0x2D02EF8D  };
		int c = 0xFFFFFFFF;
		for(int i=0;i<size;i++){
			c = ((c >> 8 ) & 0x00FFFFFF )^crc32Tab[(int)((c^pData[i])& 0xFF)];
		}
		c^=0xFFFFFFFF;
		byte[]code=new byte[4];
		code[0] = (byte) ((c >> 24) & 0xFF);
		code[1] = (byte) ((c >> 16) & 0xFF);
		code[2] = (byte) ((c >> 8) & 0xFF);
		code[3] = (byte) ((c >> 0) & 0xFF);
		return code;
	}
	public static boolean Cx62B_FCM_Level1(byte [] seed,byte [] key,int KeyK)
	{
		byte i;
		int temp_key;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		/* Xor with KeyK */
		temp_key = v_seed ^ KeyK;

		/*calculate temp_key*/
		for(i = 0;i < 32 ;i++)
		{
			if ((temp_key & (0x00000001))!= 0)
			{
				/* Rotate left 3 bits */
				temp_key = ( temp_key << 3 ) | ( temp_key >>> 29);

				/* Xor with seed */
				temp_key ^= v_seed;
			}
			else
			{
				/* Rotate right 7 bits */
				temp_key = ( temp_key >>> 7 ) | ( temp_key << 25 );

				/* Xor with KeyK */           temp_key ^= KeyK;
			}
		}

		/*calculate key*/
		//*key = temp_key;   
		key[0] = (byte) ((temp_key >>> 24) & 0xFF);
		key[1] = (byte) ((temp_key >>> 16) & 0xFF);
		key[2] = (byte) ((temp_key >>> 8) & 0xFF);
		key[3] = (byte) ((temp_key >>> 0) & 0xFF);

		/*return calculate status*/
		return true;
	}
	public static boolean Cx62B_FCM_Level2(byte [] seed,byte [] key,long KeyK)
	{
		byte i;
		int temp_key;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);

		/* Xor with KeyK */
		temp_key = (int) (v_seed ^ KeyK);

		for (i = 0; i < 32 ; i++)
		{
			if ((temp_key & (0x00000001))!= 0)
			{
				temp_key >>>= 1;
				temp_key ^= v_seed;
			}
			else
			{
				temp_key >>>= 1;
				temp_key ^= KeyK;
			}
		}

		/*calculate key*/
		//*key = temp_key;   
		key[0] = (byte) ((temp_key >>> 24) & 0xFF);
		key[1] = (byte) ((temp_key >>> 16) & 0xFF);
		key[2] = (byte) ((temp_key >>> 8) & 0xFF);
		key[3] = (byte) ((temp_key >>> 0) & 0xFF);

		/*return calculate status*/
		return true;
	}
	public static void CX62B_ABM_seedToKey(byte [] seed,byte [] key,long MASK)
	{
		byte i;
		long v_key  =  0;
		long v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		if  (v_seed  !=0  )
		{
			for  (  i=0;  i<35;  i++  )
			{
				if  ((v_seed  &  0x80000000)!= 0)
				{
					v_seed  =  v_seed  <<1;
					v_seed  =  v_seed^MASK;
				}
				else
				{
					v_seed  =  v_seed  <<  1;
				}
			}
			v_key  =  v_seed;
		}
		key[0] = (byte) ((v_key >>> 24) & 0xFF);
		key[1] = (byte) ((v_key >>> 16) & 0xFF);
		key[2] = (byte) ((v_key >>> 8) & 0xFF);
		key[3] = (byte) ((v_key >>> 0) & 0xFF);
	}
	public static void CX62B_7DCT_seedToKey(byte [] seed,byte [] key)
	{
		long v0 = (seed[0] & 0xFF) * 0x1000000 + (seed[1] & 0xFF) * 0x10000 + (seed[2] & 0xFF) * 0x100 + (seed[3] & 0xFF);
		long v1 = (~seed[0] & 0xFF) * 0x1000000 + (~seed[1] & 0xFF) * 0x10000 + (~seed[2] & 0xFF) * 0x100 + (~seed[3] & 0xFF);
		long sum = 0;
		long delta = 0x0AB01000;
		long [] k = {0,0,0,0};
		k[0] =  0x4C495551;
		k[1] =  0x49534545;
		k[2] =  0x444B4559;
		k[3] =  0x414C474F;
		for(int i = 0; i < 2; i ++)
		{
			v0 +=  (((v1 << 4) ^ ((v1 >> 5)& 0x07FFFFFF)) + v1) ^ (sum + k[(int) (sum & 3)]);
			sum += delta;
			v1 +=  (((v0 << 4) ^ ((v0 >> 5)& 0x07FFFFFF)) + v0) ^ (sum + k[(int) ((sum>>11) & 3)]);
		}
		key[0] = (byte) ((v0 >>> 24) & 0xFF);
		key[1] = (byte) ((v0 >>> 16) & 0xFF);
		key[2] = (byte) ((v0 >>> 8) & 0xFF);
		key[3] = (byte) ((v0 >>> 0) & 0xFF);
	}
	public static boolean Cx62B_EPB_Safekey(byte [] seed,byte [] key)
	{
		byte i;
		byte [] xorarray = {0x15,0x38,0x55,0x77};
		byte [] caldata = new byte[4];
		for(i = 0; i < 4; i ++)
		{
			caldata[i] = (byte) (seed[i] ^ xorarray[i]);
		}
		key[0] = (byte) (((caldata[3]&0x0F) << 4) | (caldata[3]&0xF0));
		key[1] = (byte) (((caldata[1]&0x0F) << 4) | ((caldata[0]&0xF0) >>> 4));
		key[2] = (byte) ((caldata[1]&0xF0) | ((caldata[2]&0xF0) >>> 4));
		key[3] = (byte) (((caldata[0]&0x0F) << 4) | (caldata[2]&0x0F));
		return true;
	}
}
